package com.itfreer.print.toPdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itfreer.print.TemplateFilePara;
import com.itfreer.print.base.itextpdf.ChineseFontsProvider;
import com.itfreer.print.base.itextpdf.ITextAfter;
import com.itfreer.print.base.itextpdf.ITextBefore;
import com.itfreer.print.toPdf.HtmlToPdf;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * 定义基于iText的HTML转PDF实现类
 */
@Component
public class HtmlToPdfImp implements HtmlToPdf {
	
	@Autowired(required = false)
	private TemplateFilePara templateFilePara;

	/**
	 * 输出文件
	 * 
	 * @param pdfFile 输出PDF文件
	 * @param textBefores
	 * @param textAfters
	 * @throws FileNotFoundException
	 */
	public void toPdf(OutputStream pdfFile, List<ITextBefore> textBefores, List<ITextAfter> textAfters) throws DocumentException {
		
		Rectangle rectPageSize = new Rectangle(PageSize.A4);// A4纸张 PageSize.A4.rotate() 横向
		Document document = new Document(rectPageSize, 36, 36, 36, 36);// 上、下、左、右间距

		try {
			// step 2
			PdfWriter writer = PdfWriter.getInstance(document, pdfFile);
			writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);

			if (textBefores != null && textBefores.size() > 0) {
				for (ITextBefore item : textBefores) {
					item.doOptions(document, writer);
				}
			}

			// step 3
			document.open();

			if (textAfters != null && textAfters.size() > 0) {
				for (ITextAfter item : textAfters) {
					item.doOptions(document, writer);
				}
			}
		} catch (DocumentException e) {
			e.printStackTrace();
			throw e;
		} finally {
			document.close();
		}
	}
	
	/**
	 * 输出文件
	 * 
	 * @param htmlFiel
	 *            html文件
	 * @param pdfFile
	 *            输出PDF文件
	 * @throws FileNotFoundException
	 */
	public void toPdf(InputStream htmlFile, OutputStream pdfFile) throws DocumentException, IOException {
		toPdf(htmlFile, pdfFile, null, null);
	}

	/**
	 * 输出文件
	 * 
	 * @param htmlFiel
	 *            html文件
	 * @param pdfFile
	 *            pdf文件
	 */
	public void toPdf(InputStream htmlFile, OutputStream pdfFile, List<ITextBefore> textBefores,
			List<ITextAfter> textAfters) throws FileNotFoundException, DocumentException, IOException {
		Rectangle rectPageSize = new Rectangle(PageSize.A4);// A4纸张 PageSize.A4.rotate() 横向
		Document document = new Document(rectPageSize, 36, 36, 36, 36);// 上、下、左、右间距

		try {
			// step 2
			PdfWriter writer = PdfWriter.getInstance(document, pdfFile);
			writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);

			if (textBefores != null && textBefores.size() > 0) {
				for (ITextBefore item : textBefores) {
					item.doOptions(document, writer);
				}
			}

			// step 3
			document.open();

			if (textAfters != null && textAfters.size() > 0) {
				for (ITextAfter item : textAfters) {
					item.doOptions(document, writer);
				}
			}

			ChineseFontsProvider fontProvider = new ChineseFontsProvider();
			fontProvider.setUseUnicode(true);

			// step 4
			XMLWorkerHelper.getInstance().parseXHtml(writer, document, htmlFile, Charset.forName("UTF-8"),
					fontProvider);
		} catch (DocumentException e) {
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} finally {
			document.close();
		}
	}

	/**
	 * 基于模板输出pdf文件
	 * 
	 * @param tempPath
	 *            模板文件路径
	 * @param templateFile
	 *            模板文件
	 * @param data
	 *            模板数据
	 * @param pdfFile
	 *            输出PDF文件
	 * 
	 * @throws IOException
	 * @throws TemplateException
	 * @throws DocumentException
	 */
	public void toPdf(String tempPath, String templateFile, Object data, OutputStream pdfFile)
			throws IOException, TemplateException, DocumentException {
		toPdf(tempPath, templateFile, data, pdfFile, null, null);
	}
	
	/**
	 * 基于模板输出pdf文件
	 * 
	 * @param tempPath
	 *            模板文件路径
	 * @param templateFile
	 *            模板文件
	 * @param data
	 *            模板数据
	 * @param pdfFile
	 *            输出PDF文件
	 * 
	 * @throws IOException
	 * @throws TemplateException
	 * @throws DocumentException
	 */
	@SuppressWarnings("deprecation")
	public void toPdf(String tempPath, String templateFile, Object data, OutputStream pdfFile, 
			List<ITextBefore> textBefores, List<ITextAfter> textAfters)
			throws IOException, TemplateException, DocumentException {
		ByteArrayOutputStream htmlOut = new ByteArrayOutputStream();
		OutputStreamWriter htmlWriter = new OutputStreamWriter(htmlOut, Charset.forName("UTF-8"));

		try {
			Configuration freeMarkerconfig = new Configuration();
			freeMarkerconfig.setDirectoryForTemplateLoading(new File(tempPath));
			freeMarkerconfig.setDefaultEncoding("UTF-8");
			Template freeMarkerTemplateerconfig;
			freeMarkerTemplateerconfig = freeMarkerconfig.getTemplate(templateFile, "UTF-8");
			// 往模板中写入数据
			freeMarkerTemplateerconfig.process(data, htmlWriter);
			htmlWriter.flush();
			htmlOut.flush();

			// html流
			ByteArrayInputStream htmlFile = new ByteArrayInputStream(htmlOut.toByteArray());
			toPdf(htmlFile, pdfFile, textBefores, textAfters);

			htmlFile.close();
			htmlWriter.close();
			htmlOut.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		} catch (TemplateException e) {
			e.printStackTrace();
			throw e;
		} catch (DocumentException e) {
			e.printStackTrace();
			throw e;
		}
	}

	@Override
	public void toPdf(String templateFile, Object data, OutputStream excelFile) throws Exception {
		if (templateFilePara == null) {
			return;
		}
		
		String tempPath = templateFilePara.getTemplatePath();
		if(!tempPath.contains(":\\") && !tempPath.startsWith("/")) {
			tempPath = this.getClass().getResource("/").getPath() + tempPath;
		}

		toPdf(tempPath, templateFile, data, excelFile);
	}
}
